/*

 $Id: nvcdriver.h 6 2009-10-15 06:30:15Z alex.mobilebi $
 $Date: 2009-10-15 06:30:15 +0000 (Thu, 15 Oct 2009) $
 $Author: alex.mobilebi $
 $Revision: 6 $

 Copyright(C) 2009 Alex Lee(alex@mobilebi.com)

 */


#ifndef NV_DRIVER_H
#define NV_DRIVER_H

#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/kdev_t.h>
#include <linux/pci.h>
#include <linux/cdev.h>
#include <linux/errno.h>
#include <linux/time.h>
#include <linux/workqueue.h>
#include <asm/uaccess.h>
#include <asm/io.h>

#define BUF_PACKET_SIZE 2048
#define BUF_PACKET_NUM 1024
#define MAX_HDLC_CHANNLE 256
#define MAX_TS_NUM 128
#define MAX_DEVICE_NUM 4
#define MAX_FRAMER_NUM 16
#define RX_DESC_QUEUE_SIZE     256 /* up to 1k rx descriptors allowed */
#define TX_DESC_QUEUE_SIZE     32
#define DATA_BUFFER_SIZE       512  /* one data buffer occupies 2048 bytes */
#define PACKET_DESC_LEN 16
#define RFQ_DESC_LEN 8
#define RDQ_DESC_LEN 4
#define TPQ_DESC_LEN 4
#define TDQ_DESC_LEN 4

#define OPERATION_NONE         0x00
#define OPERATION_RX           0x01
#define OPERATION_TX           0x02
#define OPERATION_MODE         OPERATION_RX
#define ENOBUF                 0x110
#define ETPQFULL               0x111
#define ERFQFULL               0x112
#define ERFQOVER               0x113

#define PCI_VENDOR_ID_DALLAS   0x13EA
#define PCI_DEVICE_ID_DS31256  0x3134

#define DS26519_BASE_ADDRESS   0x4000
#define DS31256_PCI_FN         0x00
#define DS31256_BRIDGE_FN      0x01

#define NV_IOC_MAGIC           'x'
#define NV_IOC_MAXNR           8
#define NV_IOC_WRITE_REG       _IOW(NV_IOC_MAGIC, 1, int)
#define NV_IOC_WRITE_REG_IS  _IOW(NV_IOC_MAGIC, 2, int)
#define NV_IOC_READ_REG        _IOR(NV_IOC_MAGIC, 3, int)
#define NV_IOC_RESET_PCI       _IO(NV_IOC_MAGIC, 4)
#define NV_IOC_RESET_LOCAL     _IO(NV_IOC_MAGIC, 5)
#define NV_IOC_DUMP            _IO(NV_IOC_MAGIC, 6)
#define NV_IOC_CONFIGDMA       _IO(NV_IOC_MAGIC, 7)
#define NV_IOC_EINTERRUPT      _IO(NV_IOC_MAGIC, 8)

#define REG_ADDRESS_SHIFT      16
#define REG_ADDRESS(arg)       ((arg)>>REG_ADDRESS_SHIFT)
#define REG_VALUE(arg)         ((arg)&((1U<<REG_ADDRESS_SHIFT)-1))
#define MKREG_ADDVAL(addr,val) (((addr)<<REG_ADDRESS_SHIFT)|(REG_VALUE(val)))
#define MKREG_ADDR(base, off)  ((void *)(((unsigned int)(base))|(off)))
#define VIRT_TO_PHYS(addr)     ((unsigned int)(virt_to_phys((addr))))


#define PRINT_RX_PACKETS       10240
#define PRINT_RX_DROPPED       512
#define NV_MSG_DRIVER          0x0001
#define NV_MSG_PROBE           0x0002
#define NV_MSG_REMOVE          0x0004
#define NV_MSG_READ            0x0008
#define NV_MSG_WRITE           0x0010
#define NV_MSG_IOCTL           0x0020
#define NV_MSG_OPEN            0x0040
#define NV_MSG_RELEASE         0x0080
#define NV_MSG_INTERRUPT       0x0100
#define NV_MSG_FREEDMA         0x0200
#define NV_MSG_RDMA            0x0400
#define NV_MSG_WDMA            0x0800
#define NV_MSG_INTERUPT        0x1000

#define DS31256_GCR_SDMA       0x0028
#define DS31256_GCR_ISDMA      0x002C

#define IMASK_ISDMA_RCRCE      0x0004
#define IMASK_ISDMA_RABRT      0x0008
#define IMASK_ISDMA_RLENC      0x0010
#define IMASK_ISDMA_ROVEL      0x0020
#define IMASK_ISDMA_RLBR       0x0040
#define IMASK_ISDMA_RLBRE      0x0080
#define IMASK_ISDMA_RSBR       0x0100
#define IMASK_ISDMA_RSBRE      0x0200
#define IMASK_ISDMA_RDQW       0x0400
#define IMASK_ISDMA_RDQWE      0x0800
#define IMASK_ISDMA_TUDFL      0x1000
#define IMASK_ISDMA_TPQR       0x2000
#define IMASK_ISDMA_TDQW       0x4000
#define IMASK_ISDMA_TDQWE      0x8000

#define IMASK_RIM1_RLOFD       0x01
#define IMASK_RIM1_RLOSD       0x02
#define IMASK_RIM1_RAISD       0x04
#define IMASK_RIM1_RRAID       0x08
#define IMASK_RIM1_RLOFC       0x10
#define IMASK_RIM1_RLOSC       0x20
#define IMASK_RIM1_RAISC       0x40
#define IMASK_RIM1_RRAIC       0x80
#define IMASK_RIIR_RLS1        0x01

#define OFF_LENGTH_HIGH             0
#define OFF_LENGTH_LOW              1
#define OFF_SECOND_D4               2
#define OFF_SECOND_D3               3
#define OFF_SECOND_D2               4
#define OFF_SECOND_D1               5
#define OFF_USECOND_D4              6
#define OFF_USECOND_D3              7
#define OFF_USECOND_D2              8
#define OFF_USECOND_D1              9
#define OFF_RESERVED                10
#define OFF_EVENT_TYPE              11
#define OFF_BOARD                   12
#define OFF_PORT                    13
#define OFF_CHANNEL                 13
#define OFF_STATUS                  14
#define PACKET_HEAD_LEN             14
#define PACKET_TYPE_DISCARD         0x00
#define PACKET_TYPE_DATA            0x01
#define PACKET_TYPE_STATUS          0x02

/* Definition of DS31256's Receive DMA Registers (7xx) */                                                     
#define DS31256_RDMA_RFQBA0      0x0700       /* Receive Free-Queue Base Address 0 (lower word) */                                 
#define DS31256_RDMA_RFQBA1      0x0704       /* Receive Free-Queue Base Address 1 (upper word) */ 
#define DS31256_RDMA_RFQEA       0x0708       /* Receive Free-Queue End Address */ 
#define DS31256_RDMA_RFQSBSA     0x070C       /* Receive Free-Queue Small Buffer Start Address */ 
#define DS31256_RDMA_RFQLBWP     0x0710       /* Receive Free-Queue Large Buffer Host Write Pointer */ 
#define DS31256_RDMA_RFQSBWP     0x0714       /* Receive Free-Queue Small Buffer Host Write Pointer */ 
#define DS31256_RDMA_RFQLBRP     0x0718       /* Receive Free-Queue Large Buffer DMA Read Pointer */ 
#define DS31256_RDMA_RFQSBRP     0x071C       /* Receive Free-Queue Small Buffer DMA Read Pointer */ 
#define DS31256_RDMA_RDQBA0      0x0730       /* Receive Done-Queue Base Address 0 (lower word) */ 
#define DS31256_RDMA_RDQBA1      0x0734       /* Receive Done-Queue Base Address 1 (upper word) */   
#define DS31256_RDMA_RDQEA       0x0738       /* Receive Done-Queue End Address */   
#define DS31256_RDMA_RDQRP       0x073C       /* Receive Done-Queue Host Read Pointer */   
#define DS31256_RDMA_RDQWP       0x0740       /* Receive Done-Queue DMA Write Pointer */   
#define DS31256_RDMA_RDQFFT      0x0744       /* Receive Done-Queue FIFO Flush Timer */   
#define DS31256_RDMA_RDBA0       0x0750       /* Receive Descriptor Base Address 0 (lower word) */   
#define DS31256_RDMA_RDBA1       0x0754       /* Receive Descriptor Base Address 1 (upper word) */   
#define DS31256_RDMA_RDMACIS     0x0770       /* Receive DMA Configuration Indirect Select */   
#define DS31256_RDMA_RDMAC       0x0774       /* Receive DMA Configuration */   
#define DS31256_RDMA_RDMAQ       0x0780       /* Receive DMA Queues Control */   
#define DS31256_RDMA_RLBS        0x0790       /* Receive Large Buffer Size */ 
#define DS31256_RDMA_RSBS        0x0794       /* Receive Small Buffer Size */ 
                                                                                                              
/* Definition of DS31256's Transmit DMA Registers (8xx) */                                                  
#define DS31256_TDMA_TPQBA0      0x0800       /* Transmit Pending-Queue Base Address 0 (lower word) */ 
#define DS31256_TDMA_TPQBA1      0x0804       /* Transmit Pending-Queue Base Address 1 (upper word) */ 
#define DS31256_TDMA_TPQEA       0x0808       /* Transmit Pending-Queue End Address */ 
#define DS31256_TDMA_TPQWP       0x080C       /* Transmit Pending-Queue Host Write Pointer */ 
#define DS31256_TDMA_TPQRP       0x0810       /* Transmit Pending-Queue DMA Read Pointer */ 
#define DS31256_TDMA_TDQBA0      0x0830       /* Transmit Done-Queue Base Address 0 (lower word) */ 
#define DS31256_TDMA_TDQBA1      0x0834       /* Transmit Done-Queue Base Address 1 (upper word) */ 
#define DS31256_TDMA_TDQEA       0x0838       /* Transmit Done-Queue End Address */ 
#define DS31256_TDMA_TDQRP       0x083C       /* Transmit Done-Queue Host Read Pointer */ 
#define DS31256_TDMA_TDQWP       0x0840       /* Transmit Done-Queue DMA Write Pointer */ 
#define DS31256_TDMA_TDQFFT      0x0844       /* Transmit Done-Queue FIFO Flush Timer */ 
#define DS31256_TDMA_TDBA0       0x0850       /* Transmit Descriptor Base Address 0 (lower word) */ 
#define DS31256_TDMA_TDBA1       0x0854       /* Transmit Descriptor Base Address 1 (upper word) */ 
#define DS31256_TDMA_TDMACIS     0x0870       /* Transmit DMA Configuration Indirect Select */
#define DS31256_TDMA_TDMAC       0x0874       /* Transmit DMA Configuration */ 
#define DS31256_TDMA_TDMAQ       0x0880       /* Transmit DMA Queues Control */

#define DS26519_GR_GFISR1        0x00F9	      /* Global Framer Interrupt Status Register 1 */
#define DS26519_GR_GFISR2        0x20F9       /* Global Framer Interrupt Status Register 2 */
#define DS26519_FRAMER_RLS1      0x0090	      /* Receive Latched Status Register 1 */  
#define DS26519_FRAMER_RIIR      0x009F	      /* Receive Interrupt Information Register */

typedef struct tagdmaDesc
{
	unsigned int dataAddr;//dword 0 = data buffer address,
        unsigned int desc1;    //dword 1 bit[0 - 15] = next descriptor Pointer; bit[16 - 28] = Byte Count; bit[29 - 31] = BUFS
        unsigned int desc2;    //dword 2 bit[ 0 - 7] = HDLC Channel; bit[8 - 31] = Timestamp (unused in Tx packet descriptor)
        unsigned int desc3;    //dword 3 unused in Rx packet descriptor
}dmaDesc,*dmaDescPtr;

typedef struct tagRxFreeDesc
{
	unsigned int dataAddr;/* dword 0 = free data buffer address,dword 1 = free desc.Ptr */
        unsigned int desc;
} dmaRxFreeDesc,*dmaRxFreeDescPtr;

typedef struct tagXXDesc
{
    unsigned int desc;
}dmaRxDoneDesc,dmaTxPendDesc,dmaTxDoneDesc,*dmaRxDoneDescPtr,*dmaTxPendDescPtr,*dmaTxDoneDescPtr;

typedef struct tagRxDMA
{
//	//nvRfqPtr rfq_base_addr;        /* Rx free quene base address */
//    unsigned char * rfq_base_addr;
//	//nvRdqPtr rdq_base_addr;        /* Rx done quene base address */
//    unsigned char * rdq_base_addr;
//	//nvPacketPtr rx_desc_base_addr; /* packet descriptor base address */
//    unsigned char * rx_desc_base_addr;
//    unsigned char * rx_buf_base_addr;       /* Rx data buffer base address */
    dmaDescPtr descQStart;  //packet descriptor base address
    dmaRxFreeDescPtr freeQStart; //Rx free queue start address
    dmaRxDoneDescPtr doneQStart; //Rx done queue start address
    unsigned char * dataBufAddr;//Rx data buffer base address
}dmaRxDev,*dmaRxDevPtr;

typedef struct tagnvTxDMA
{
//	//nvTpqPtr tpq_base_addr;        /* Tx pending quene base address */
//    unsigned char * tpq_base_addr;
//	//nvTdq * tdq_base_addr;         /* Tx done quene base address */
//    unsigned char * tdq_base_addr;
//	//nvPacketPtr tx_desc_base_addr; /* Tx data buffer base address */
//    unsigned char * tx_desc_base_addr;
    dmaDescPtr descQStart;
    dmaTxPendDescPtr pendQStart;
    dmaTxDoneDescPtr doneQStart;
}dmaTxDev, *dmaTxDevPtr;

typedef struct tagnvDevice
{
	unsigned short operation;  /* operation mode ,Rx or Tx or Rx&Tx */
	void *ioaddr;              /* remaped MMIO base address of PCI device */
	unsigned int irq;          /* interrupt num of PCI device allocated by system */
	unsigned int devfn;        /* function 0 for PCI operation,and function 1 for local bridge */
	struct pci_dev *pdev;      /* the pointer to PCI device */
	dmaRxDevPtr rdma;    /* Rx DMA data struct */
	dmaTxDevPtr tdma;    /* Tx DMA data struct */
	unsigned int rx_packets;   /* Received packets */
	unsigned int rx_dropped;   /* Dropped Rx packets */
	//unsigned int tx_packets;
	//unsigned int tx_dropped;
	struct cdev device;        /* char device struct register to system */
	dev_t dev_id;              /* device id consists of Major & Minor */
	struct work_struct my_work;/* workqueue for receive packets */
} nvDevice, *nvDevicePtr;

static ssize_t nv_read(struct file *filp, char __user *buff, size_t count, loff_t *offp);
static ssize_t nv_write(struct file *filp, const char __user *buff, size_t count, loff_t *offp);
static int nv_open(struct inode *node, struct file *filp);
static int nv_release(struct inode *node, struct file *filp);
static int nv_ioctl(struct inode *node, struct file *filp, unsigned int cmd, unsigned long arg);
static void enable_interrupt(nvDevicePtr ndev, char irq_op);
static int __devinit nv_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
static void __devexit nv_remove(struct pci_dev *pdev);
static irqreturn_t nv_interrupt(int irq, void *dev, struct pt_regs * regs);
static void nv_do_work(struct work_struct * work);
static void fill_time_field(void);
static void proc_data_packet(nvDevicePtr ndev);
static void proc_data_status(nvDevicePtr ndev);
static void encap_status_packet(unsigned char device, unsigned char port, unsigned char status);
static int nv_suspend(struct pci_dev *pdev, pm_message_t state);
static int nv_resume(struct pci_dev *pdev);
static int __init nv_init_module(void);
static void __exit nv_exit_module(void);
static void release_driver_buffer(void);
static dmaRxDevPtr alloc_rx_dma(void);
static dmaTxDevPtr alloc_tx_dma(void);
static void free_rx_dma(dmaRxDevPtr rdma);
static void free_tx_dma(dmaTxDevPtr tdma);
static void free_tx_data(const dmaDescPtr descStart);
static void free_user_data(const dmaDescPtr ptr);
static int read_from_dma(nvDevicePtr ndev, char * buff, size_t count);
static void set_rw_pos(unsigned int * rw_pos, int inc);
static int get_buf_cnt_to_write(int windex, int rindex);
static int get_buf_cnt_to_read(int rindex, int windex);
static int get_packet(void * to, const unsigned short desc_ind, const dmaDescPtr start, const unsigned short count);
static void write_rx_free_queue(void * ioaddr, unsigned short desc_ind, dmaRxDevPtr rdma_ptr);
static void write_rx_done_queue(void * ioaddr, unsigned short rd_ind);
static int get_packet_size(const unsigned short desc_ind, const dmaDescPtr start);
static int write_to_dma(nvDevicePtr ndev, const char __user * buff, size_t count);
static void check_tx_done_queue(nvDevicePtr ndev);
static int requeue_tx_packet(const unsigned short desc, nvDevicePtr ndev);
static int queue_tx_pending_packet(nvDevicePtr ndev, const unsigned short channel, const unsigned int data, unsigned long count, char pri);
static int config_dma(nvDevicePtr ndev);
static unsigned int read_regs(void * addr, char flag);
static void write_regs(void * addr, unsigned short value, char flag);
static void write_regs_is(void * addr, unsigned short value, char flag);
static nvDevicePtr alloc_nv_device(void);
static int register_nv_device(nvDevicePtr ndev);
static int init_nv_device(nvDevicePtr ndev);
static void free_nv_device(nvDevicePtr ndev);
static void print_rdma(const dmaRxDevPtr rdma);
static void print_tdma(const dmaTxDevPtr tdma);
static void dump(nvDevicePtr ndev);
static void dump_rx(void * ioaddr, dmaRxDevPtr rxDev);
static void dump_tx(void * ioaddr, dmaTxDevPtr txDev);

#endif                                      
